#include "varifyGrpcClient.h"
#include "configMgr.h"

varifyGrpcClient& varifyGrpcClient::GetInst()
{
	static varifyGrpcClient instance;
	return instance;
}
message::GetVarifyRsp varifyGrpcClient::GetVarifyCode(std::string email)
{
	ClientContext context;
	message::GetVarifyReq request;
	message::GetVarifyRsp reply;
	request.set_email(email);
	auto stub = _pool->getStub();
	Status status = stub->GetVarifyCode(&context, request, &reply);
	if (!status.ok()) {
		reply.set_error(ErrorCodes::RPCFailed);
	}
	_pool->returnStub(std::move(stub));
	return reply;
}
varifyGrpcClient::varifyGrpcClient() {
	auto& configMgr = configMgr::GetInst();
	_pool = std::make_unique<RPConnectPool>(5, configMgr["VarifyServer"]["host"], configMgr["VarifyServer"]["port"]);
	

 }

RPConnectPool::RPConnectPool(size_t poolsize, std::string host, std::string port):_poolsize(poolsize),_host(host),_port(port),
_b_stop(false)
{
	for (size_t i = 0;i < poolsize;++i) {
		std::shared_ptr<Channel> channel = grpc::CreateChannel(host+":"+port, grpc::InsecureChannelCredentials());
		/*_stubs.push(message::VarifyService::NewStub(channel));*/
		_stubs.emplace(message::VarifyService::NewStub(channel));
	}
}

RPConnectPool::~RPConnectPool()
{
	std::lock_guard<std::mutex> lock(_mtx);
	Close();
	while (!_stubs.empty()) {
		_stubs.pop();
	}
	
}

void RPConnectPool::Close()
{
	_b_stop = true;
	_condvar.notify_all();
}

std::unique_ptr<message::VarifyService::Stub> RPConnectPool::getStub()
{
	std::unique_lock<std::mutex> lock(_mtx);
	_condvar.wait(lock, [this]() {
		if (_b_stop) {
			return true;
			}
		return !_stubs.empty();
		});
	if (_b_stop) {
		return nullptr;
	}

	auto stub = std::move(_stubs.front());
	_stubs.pop();
	return stub;
}

void RPConnectPool::returnStub(std::unique_ptr<message::VarifyService::Stub> stub)
{
	std::lock_guard<std::mutex> lock(_mtx);
	if (_b_stop) {
		return;
	}
	_stubs.push(std::move(stub));
	_condvar.notify_one();  
}
